home *** CD-ROM | disk | FTP | other *** search
/ Libris Britannia 4 / science library(b).zip / science library(b) / DJGPP / DJLSR111.ZIP / libsrc / pc / src / gppconio.c < prev    next >
C/C++ Source or Header  |  1993-10-09  |  19KB  |  738 lines

  1. /**********************************************************************
  2.  *  
  3.  *  NAME:           gppconio.c
  4.  *  
  5.  *  DESCRIPTION:    simulate Borland text video funcs for GNU C++
  6.  *  
  7.  *  copyright (c) 1991 J. Alan Eldridge
  8.  * 
  9.  *  M O D I F I C A T I O N   H I S T O R Y
  10.  *
  11.  *  when        who                 what
  12.  *  -------------------------------------------------------------------
  13.  *  10/27/91    J. Alan Eldridge    created
  14.  *  01/06/92    D. Buerssner        make it work with extended characters
  15.  * (buers@dg1.chemie.uni-konstanz.de) speed-up of cputs
  16.  *                                  some missing brackets in VIDADDR
  17.  *                                  don't need scrollwindow anymore
  18.  *  07/15/93    D. Buerssner        take care of cursor tracking
  19.  *                                    txinfo.curx and txinfo.cury
  20.  *                                  fill in missing functionality
  21.  *                                    - textmode
  22.  *                                    - cscanf
  23.  *                                    - cgets
  24.  *                                    - getch and ungetch
  25.  *                                    - _setcursortype
  26.  *                                    - kbhit 
  27.  *                                  (hpefully) proper initialization of
  28.  *                                    txinfo.normattrib and txinfo.attribute  
  29.  *                                  gotoxy(1,1) in clrscr (bug introduced
  30.  *                                    by my previous patches)
  31.  *                                  gotoxy(1,1) in window
  32.  *                                  take care of BELL and BACKSPACE
  33.  *                                    in putch and cputs
  34.  *                                  take care of blinking bit in textcolor
  35.  *                                    and textbackground
  36.  *                                  declare (and ignore) directvideo 
  37.  *  10/09/93    DJ Delorie          Switch to dosmem*() for DPMI
  38.  *********************************************************************/
  39.  
  40. #include    <stdlib.h>
  41. #include    <stdio.h>
  42. #include    <stdarg.h>
  43. #include    <dos.h>
  44. #include    <pc.h>
  45. #include    <go32.h>
  46. #include    "gppconio.h"
  47.  
  48. int directvideo = 1;  /* We ignore this */
  49.  
  50. static void setcursor(unsigned int shape);
  51. static int getvideomode(void);
  52. static void bell(void);
  53. static int get_screenattrib(void);
  54. static int isEGA(void);
  55. static int _scan_getche(FILE *fp);
  56. static int _scan_ungetch(int c, FILE *fp);
  57.  
  58. #define DBGGTINFO   0
  59.  
  60. static unsigned ScreenAddress = 0xb8000UL; /* initialize just in case */
  61. static struct text_info txinfo;
  62. static int ungot_char;
  63. static int char_avail = 0;
  64.  
  65. #define VIDADDR(r,c) (ScreenAddress + 2*(((r) * txinfo.screenwidth) + (c)))
  66.  
  67. int puttext(int c, int r, int c2, int r2, void *buf)
  68. {
  69.   short *cbuf = (short *)buf;
  70.   /* we should check for valid parameters, and maybe return 0 */
  71.   r--, r2--, c--, c2--;
  72.   for (; r <= r2; r++)
  73.   {
  74.     dosmemput(cbuf, (c2-c+1)*2, VIDADDR(r, c));
  75.     cbuf += c2-c+1;
  76.   }
  77.   return 1;
  78. }
  79.  
  80. int gettext(int c, int r, int c2, int r2, void *buf)
  81. {
  82.   short *cbuf = (short *)buf;
  83.   /* we should check for valid parameters, and maybe return 0 */
  84.   r--, r2--, c--, c2--;
  85.   for (; r <= r2; r++)
  86.   {
  87.     dosmemget(VIDADDR(r, c), (c2-c+1)*2, cbuf);
  88.     cbuf += c2-c+1;
  89.   }
  90.   return 1;
  91. }
  92.         
  93. void gotoxy(int col, int row)
  94. {
  95.   ScreenSetCursor(row + txinfo.wintop - 2, col + txinfo.winleft - 2);
  96.   txinfo.curx = col;
  97.   txinfo.cury = row;
  98. }
  99.  
  100. int wherex(void)
  101. {
  102.   int row, col;
  103.   
  104.   ScreenGetCursor(&row, &col);
  105.   
  106.   return col - txinfo.winleft + 2;
  107. }
  108.     
  109. int wherey(void)
  110. {
  111.   int row, col;
  112.   
  113.   ScreenGetCursor(&row, &col);
  114.   
  115.   return row - txinfo.wintop + 2;
  116. }
  117.  
  118. void textmode(int mode)
  119. {
  120.     union REGS regs;
  121.     int mode_to_set = mode;
  122.     if (mode == LASTMODE)
  123.         mode = mode_to_set = txinfo.currmode;
  124.     if (mode == C4350)
  125.         /* 
  126.          * just set mode 3 and load 8x8 font, idea taken 
  127.          * (and code translated from Assembler to C)
  128.          * form Csaba Biegels stdvga.asm
  129.          */
  130.         mode_to_set = 0x03;  
  131.     regs.h.ah = 0x00; /* set mode */
  132.     regs.h.al = mode_to_set;
  133.     int86(0x10, ®s, ®s);
  134.     if (mode == C80 || mode == BW80 || mode == C4350)
  135.     {
  136.         if (isEGA())
  137.         {
  138.             /* 
  139.              * enable cursor size emulation, see Ralf Browns
  140.              * interrupt list
  141.              */
  142.             regs.h.ah = 0x12;
  143.             regs.h.bl = 0x34;
  144.             regs.h.al = 0x00; /* 0: enable (1: disable) */
  145.             int86(0x10, ®s, ®s);
  146.     }
  147.     }
  148.     if (mode == C4350)
  149.     {
  150.         if (!isEGA())
  151.             return;
  152.         /* load 8x8 font */
  153.         regs.x.ax = 0x1112;         
  154.         regs.x.bx = 0;
  155.         int86(0x10, ®s, ®s);
  156.     }
  157. /*    _setcursortype(_NORMALCURSOR); */
  158.     /* reinitialize txinfo structure to take into account new mode */
  159.     gppconio_init();
  160. #if 0
  161.     /*
  162.      * For mode C4350 the screen is not cleared on my OAK-VGA.
  163.      * Should we clear it here? TURBOC doesn't so we don't bother either.
  164.      */
  165.     clrscr();
  166. #endif
  167. }    
  168.     
  169. void textattr(int attr)
  170. {
  171.   txinfo.attribute = ScreenAttrib = (unsigned char)attr;
  172. }
  173.  
  174. void textcolor(int color)
  175. {
  176.   /* strip blinking (highest) bit and textcolor */
  177.   ScreenAttrib &= 0x70; /* strip blinking (highest) bit and textcolor */
  178.   txinfo.attribute=(ScreenAttrib |= (color & 0x8f));
  179. }
  180.  
  181. void textbackground(int color)
  182. {
  183.   /* strip background color, keep blinking bit */
  184.   ScreenAttrib &= 0x8f; 
  185.   /* high intensity background colors (>7) are not allowed 
  186.      so we strip 0x08 bit (and higher bits) of color */
  187.   txinfo.attribute=(ScreenAttrib |= ((color & 0x07) << 4));
  188. }
  189.  
  190. void highvideo(void)
  191. {
  192.   txinfo.attribute=(ScreenAttrib |= 0x08);
  193. }
  194.  
  195. void lowvideo(void)
  196. {
  197.   txinfo.attribute=(ScreenAttrib &= 0x07);
  198. }
  199.  
  200. void normvideo(void)
  201. {
  202.   txinfo.attribute = ScreenAttrib = txinfo.normattr;
  203. }
  204.  
  205. void _setcursortype(int type)
  206. {
  207.     unsigned cursor_shape;
  208.     switch (type)
  209.     {
  210.         case _NOCURSOR:
  211.             cursor_shape = 0x0700;
  212.             break;
  213.         case _SOLIDCURSOR:
  214.             cursor_shape = 0x0007;
  215.             break;
  216. /*      case _NORMALCURSOR: */
  217.         default:
  218.             cursor_shape = 0x0607;
  219.             break;
  220.     }
  221.     setcursor(cursor_shape);
  222. }        
  223.  
  224. static void setcursor(unsigned int cursor_shape)
  225. /* Sets the shape of the cursor */
  226. {
  227.     union REGS      reg;
  228.  
  229.     reg.h.ah = 1;
  230.     reg.x.cx = cursor_shape;
  231.     int86(0x10, ®, ®);
  232. }                /* setcursor */
  233.  
  234. static void getwincursor(int *row, int *col)
  235. {
  236.   ScreenGetCursor(row, col);
  237. }
  238.  
  239. void clreol(void)
  240. {
  241.   short   image[ 256 ];
  242.   short   val = ' ' | (ScreenAttrib << 8);
  243.   int     c, row, col, ncols;
  244.   
  245.   getwincursor(&row, &col);
  246.   ncols = txinfo.winright - col;
  247.   
  248.   for (c = 0; c < ncols; c++)
  249.     image[ c ] = val;
  250.   
  251.   puttext(col + 1, row + 1, txinfo.winright, row + 1, image);
  252. }
  253.  
  254. static void fillrow(int row, int left, int right, int fill)
  255. {
  256.   int col;
  257.   short filler[right-left+1];
  258.   
  259.   for (col = left; col <= right; col++)
  260.     filler[col-left] = fill;
  261.   dosmemput(filler, (right-left+1)*2, VIDADDR(row, left));
  262. }
  263.  
  264. void clrscr(void)
  265. {
  266.   short filler[txinfo.winright - txinfo.winright + 1];
  267.   int row, col;
  268.   for (col=0; col < txinfo.winright - txinfo.winright + 1; col++)
  269.     filler[col] = ' ' | (ScreenAttrib << 8);
  270.   for (row=txinfo.wintop-1; row < txinfo.winbottom; row++)
  271.     dosmemput(filler, (txinfo.winright - txinfo.winright + 1)*2, VIDADDR(row, txinfo.winleft));
  272.   gotoxy(1, 1);
  273. }
  274.  
  275. int putch(int c)
  276. {
  277.   int     row, col;
  278.   
  279.   ScreenGetCursor(&row, &col);
  280.   
  281.   /*  first, handle the character */
  282.   if (c == '\n')
  283.     {
  284.       row++;
  285.     }
  286.   else if (c == '\r')
  287.     {
  288.       col = txinfo.winleft - 1;
  289.     }
  290.   else if (c == '\b')
  291.   {
  292.       if (col > txinfo.winleft - 1)
  293.           col--;  
  294.       else if (row > txinfo.wintop -1)
  295.       {
  296.           /* 
  297.            * Turbo-C ignores this case; we are smarter.
  298.            */
  299.           row--;
  300.           col = txinfo.winright-1;
  301.       }  
  302.   }      
  303.   else if (c == 0x07)
  304.     bell();
  305.   else {
  306.     short   val = c | (ScreenAttrib << 8);
  307.     /* puttext(col + 1, row + 1, col + 1, row + 1, &val); */
  308.     ScreenPutChar(c, ScreenAttrib, row, col);
  309.     col++;
  310.   }
  311.   
  312.   /* now, readjust the window     */
  313.   
  314.   if (col >= txinfo.winright) {
  315.     col = txinfo.winleft - 1;
  316.     row++;
  317.   }
  318.   
  319.   if (row >= txinfo.winbottom) {
  320.     /* scrollwin(0, txinfo.winbottom - txinfo.wintop, 1); */
  321.     ScreenSetCursor(txinfo.wintop-1,0);
  322.     delline();
  323.     row--;
  324.   }
  325.   
  326.   ScreenSetCursor(row, col);
  327.   txinfo.cury = row - txinfo.wintop + 2;
  328.   txinfo.curx = col - txinfo.winleft + 2;
  329.   return c;
  330. }
  331.  
  332. int getche(void)
  333. {
  334.   if (char_avail)
  335.     /*
  336.      * We don't know, wether the ungot char was already echoed
  337.      * we assume yes (for example in cscanf, probably the only
  338.      * place where ungetch is ever called.
  339.      * There is no way to check for this really, because
  340.      * ungetch could have been called with a character that
  341.      * hasn't been got by a conio function.
  342.      * We don't echo again.
  343.      */ 
  344.     return(getch());
  345.   return (putch(getch()));
  346. }
  347.  
  348. int getch(void)
  349. {
  350.     union REGS regs;
  351.     int c;
  352.     if (char_avail)
  353.     {
  354.         c = ungot_char;
  355.         char_avail = 0;
  356.     }
  357.     else
  358.     {
  359.         regs.x.ax = 0x0700;
  360.         int86(0x21, ®s, ®s);
  361.         c = regs.h.al;
  362.     }
  363.     return(c);
  364. }
  365.  
  366. int ungetch(int c)
  367. {
  368.     if (char_avail)
  369.         return(EOF);
  370.     ungot_char = c;
  371.     char_avail = 1;
  372.     return(c);
  373. }
  374.  
  375. /* 
  376.  * kbhit from libc in libsrc/c/dos/kbhit.s doesn't check
  377.  * for ungotten chars, so we have to provide a new one
  378.  * Don't call it kbhit, rather use a new name (_conio_kbhit)
  379.  * and do a #define kbhit _conio_kbhit in gppconio.h.
  380.  * The old kbhit still can be used if gppconio.h
  381.  * is not included of after #undef kbhit
  382.  * If you don't use ungetch (directly or indirectly by cscanf)
  383.  * both kbhit and _conio_kbhit are the same.
  384.  * So this shouldn't cause any trouble with previously written
  385.  * source, because ungetch wasn't available.
  386.  * The only problem might be, if anybody just included gppconio.h
  387.  * and has not linked with libpc, (I can't think of a good reason
  388.  * for this). This will result a link error (undefined symbol _conio_kbhit).
  389.  */
  390.  
  391. #undef kbhit  /* want to be able to call kbhit from libc */
  392.  
  393. int _conio_kbhit(void)
  394. {
  395.     if (char_avail)
  396.         return(1);
  397.     else
  398.         return(kbhit());
  399. }    
  400.  
  401. /*
  402.  * The next two functions are needed by cscanf
  403.  */
  404. static int _scan_getche(FILE *fp)
  405. {
  406.     return(getche());
  407. }
  408.  
  409. static int _scan_ungetch(int c, FILE *fp)
  410. {
  411.     return(ungetch(c));
  412. }
  413.  
  414.  
  415. void insline(void)
  416. {
  417.   int row, col, left, right, nbytes, bot, fill;
  418.   short line[txinfo.winright - txinfo.winleft + 1];
  419.   ScreenGetCursor(&row, &col);
  420.   left = txinfo.winleft - 1;
  421.   right = txinfo.winright - 1;
  422.   nbytes = (right-left+1)*2;
  423.   bot = txinfo.winbottom-1;
  424.   fill = ' ' | (ScreenAttrib << 8);
  425.   while(bot > row+1)
  426.     {
  427.       movedata(_go32_conventional_mem_selector(), VIDADDR(bot-1, left),
  428.                _go32_conventional_mem_selector(), VIDADDR(bot, left),
  429.                nbytes);
  430.       bot--;
  431.     }
  432.   if (row < txinfo.winbottom -1)
  433.     {
  434.       fillrow(row+1,left,right,fill);
  435.     }
  436. }
  437.  
  438.  
  439. void delline(void)
  440. {
  441.   int row, col, left, right, nbytes, bot, fill;
  442.   ScreenGetCursor(&row, &col);
  443.   left = txinfo.winleft - 1;
  444.   right = txinfo.winright - 1;
  445.   nbytes = (right-left+1)*2;
  446.   bot = txinfo.winbottom-1;
  447.   fill = ' ' | (ScreenAttrib << 8);
  448.   while(row < bot)
  449.     {
  450.       movedata(_go32_conventional_mem_selector(), VIDADDR(row+1, left),
  451.                _go32_conventional_mem_selector(), VIDADDR(row, left),
  452.                nbytes);
  453.       row++;
  454.     }
  455.   fillrow(bot,left,right,fill);
  456. }
  457.  
  458.  
  459. void window(int left, int top, int right, int bottom)
  460. {
  461.   if (top < 1 || left < 1 || right > txinfo.screenwidth ||
  462.       bottom > txinfo.screenheight)
  463.     return;
  464.   
  465.   txinfo.wintop = top;
  466.   txinfo.winleft = left;
  467.   txinfo.winright = right;
  468.   txinfo.winbottom = bottom;
  469.   gotoxy(1,1);
  470. }
  471.  
  472.  
  473. int cputs(const char *s)
  474. {
  475.   int     row, col,c;
  476.   const unsigned char *ss = (const unsigned char *)s;
  477.   short *viaddr;
  478.   short sa = ScreenAttrib << 8;
  479.   ScreenGetCursor(&row, &col);
  480.   viaddr = (short *)VIDADDR(row,col);
  481.   /* 
  482.    * Instead of just calling putch; we do everything by hand here,
  483.    * This is much faster. We don't move the cursor after each character,
  484.    * only after the whole string is written, because ScreenSetCursor
  485.    * needs to long because of switching to real mode needed with djgpp. 
  486.    * You won't recognize the difference.
  487.    */
  488.   while (c = *ss++)
  489.     {
  490.       /*  first, handle the character */
  491.       if (c == '\n')
  492.     {
  493.       row++;
  494.       viaddr += txinfo.screenwidth;
  495.     }
  496.       else if (c == '\r')
  497.     {
  498.       col = txinfo.winleft - 1;
  499.       viaddr = (short *)VIDADDR(row,col);
  500.     }
  501.       else if (c == '\b')
  502.         {
  503.           if (col > txinfo.winleft-1) 
  504.           {
  505.               col--;
  506.               viaddr--;
  507.           }
  508.           else if (row > txinfo.wintop -1)
  509.           {
  510.               /* 
  511.                * Turbo-C ignores this case. We want to be able to
  512.                * edit strings with backspace in gets after
  513.                * a linefeed, so we are smarter
  514.                */
  515.               row--;
  516.               col = txinfo.winright-1;
  517.               viaddr = (short *)VIDADDR(row,col);
  518.           }
  519.         }
  520.       else if (c == 0x07)
  521.           bell();
  522.       else {
  523.         short q = c | sa;
  524.         dosmemput(&q, 2, (int)viaddr);
  525.     viaddr++;
  526.     col++;
  527.       }
  528.       
  529.       /* now, readjust the window     */
  530.       
  531.       if (col >= txinfo.winright) {
  532.     col = txinfo.winleft - 1;
  533.     row++;
  534.     viaddr = (short *)VIDADDR(row,col);
  535.       }
  536.       
  537.       if (row >= txinfo.winbottom) {
  538.     ScreenSetCursor(txinfo.wintop-1,0); /* goto first line in window */
  539.     delline();                          /* and delete it */
  540.     row--;
  541.     viaddr -= txinfo.screenwidth;
  542.       }
  543.     }
  544.   
  545.   ScreenSetCursor(row, col);
  546.   txinfo.cury = row - txinfo.wintop + 2;
  547.   txinfo.curx = col - txinfo.winleft + 2;
  548.   return(*(--ss));
  549. }
  550.  
  551.  
  552. int cprintf(const char *fmt, ...)
  553. {
  554.   int     cnt;
  555.   char    buf[ 2048 ]; /* this is buggy, because buffer might be too small. */
  556.   va_list ap;
  557.   
  558.   va_start(ap, fmt);
  559.   cnt = vsprintf(buf, fmt, ap);
  560.   va_end(ap);
  561.   
  562.   cputs(buf);
  563.   return cnt;
  564. }
  565.  
  566. char *cgets(char *string)
  567. {
  568.     unsigned len = 0;
  569.     unsigned int maxlen_wanted;
  570.     char *sp;
  571.     int c;
  572.     /*
  573.      * Be smart and check for NULL pointer.
  574.      * Don't know wether TURBOC does this.
  575.      */
  576.     if (!string)
  577.         return(NULL);
  578.     maxlen_wanted = (unsigned int)((unsigned char)string[0]);
  579.     sp = &(string[2]);
  580.     /* 
  581.      * Should the string be shorter maxlen_wanted including or excluding
  582.      * the trailing '\0' ? We don't take any risk.
  583.      */
  584.     while(len < maxlen_wanted-1)
  585.     {
  586.         c=getch();
  587.         /*
  588.          * shold we check for backspace here?
  589.          * TURBOC does (just checked) but doesn't in cscanf (thats harder
  590.          * or even impossible). We do the same.
  591.          */
  592.         if (c == '\b')
  593.         {
  594.             if (len > 0)
  595.             {
  596.                cputs("\b \b"); /* go back, clear char on screen with space
  597.                                   and go back again */
  598.                len--;
  599.                sp[len] = '\0'; /* clear the character in the string */
  600.             }
  601.         }
  602.         else if (c == '\r')
  603.         {
  604.             sp[len] = '\0';
  605.             break;
  606.         }
  607.         else if (c == 0)
  608.         {
  609.             /* special character ends input */
  610.             sp[len] = '\0';
  611.             ungetch(c); /* keep the char for later processing */
  612.             break;
  613.         }
  614.         else
  615.         {
  616.            sp[len] = putch(c);
  617.            len++;
  618.         }
  619.      }
  620.      sp[maxlen_wanted-1] = '\0';
  621.      string[1] = (char)((unsigned char)len);
  622.      return(sp);   
  623. }    
  624.  
  625. int cscanf(const char *fmt, ...)
  626. {
  627.     return(_doscan_low(NULL, _scan_getche, _scan_ungetch, 
  628.                        fmt, (void **)((&fmt)+1)));
  629. }
  630.  
  631. int movetext(int left, int top, int right, int bottom, int dleft, int dtop)
  632. {
  633.   char    *buf = malloc((right - left + 1) * (bottom - top + 1) * 2);
  634.   
  635.   if (!buf)
  636.     return 0;
  637.   
  638.   gettext(left, top, right, bottom, buf);
  639.   puttext(dleft, dtop, dleft + right - left, dtop + bottom - top, buf);
  640.   free(buf);
  641.   return 1;
  642. }
  643.  
  644. static void _gettextinfo(struct text_info *t)
  645. {
  646.   int row, col;
  647.   
  648.   t->winleft = t->wintop = 1;
  649.   t->winright = t->screenwidth = ScreenCols();
  650.   t->winbottom = t->screenheight = ScreenRows();
  651.   ScreenAttrib = t->attribute = t->normattr = get_screenattrib();
  652.   t->currmode = getvideomode();
  653.   ScreenGetCursor(&row, &col);
  654.   t->curx = col+1;
  655.   t->cury = row+1;
  656. #if DBGGTINFO
  657.   printf("left=%2d,right=%2d,top=%2d,bottom=%2d\n",t->winleft,
  658.      t->winright,t->wintop,t->winbottom);
  659.   printf("scrht=%2d,scrwid=%2d,norm=%2x,mode=%2d,x=%2d,y=%2d\n",
  660.      t->screenheight, t->screenwidth, t->normattr, t->currmode,
  661.      t->curx, t->cury);
  662. #endif
  663. }
  664.  
  665. void gettextinfo(struct text_info *t)
  666. {
  667.   *t = txinfo; 
  668. #if DBGGTINFO
  669.   printf("left=%2d,right=%2d,top=%2d,bottom=%2d\n",t->winleft,
  670.      t->winright,t->wintop,t->winbottom);
  671.   printf("scrht=%2d,scrwid=%2d,norm=%2x,mode=%2d,x=%2d,y=%2d\n",
  672.      t->screenheight, t->screenwidth, t->normattr, t->currmode,
  673.      t->curx, t->cury);
  674. #endif
  675. }
  676.  
  677. static int
  678. getvideomode(void)
  679. {
  680.     int mode = ScreenMode();
  681.     /* 
  682.      * in mode C80 we might have loaded a different font
  683.      */
  684.     if (mode == C80)
  685.         if (ScreenRows() > 25)
  686.            mode = C4350;
  687.     return(mode);
  688. }
  689.     
  690.  
  691. static void bell(void)
  692. {
  693.     union REGS regs;
  694.     regs.h.ah = 0x0e; /* write */
  695.     regs.h.al = 0x07; /* bell */
  696.     int86(0x10, ®s, ®s);
  697. }
  698.  
  699. static int 
  700. get_screenattrib(void)
  701. {
  702.     union REGS regs;
  703.     regs.h.ah = 0x08; /* read character and attribute */
  704.     regs.h.bh = 0;    /* video page 0 */
  705.     int86(0x10, ®s, ®s);
  706.     return(regs.h.ah & 0x7f); /* strip highest (BLINK) bit */
  707. }
  708.  
  709. /* check if we have at least EGA (idea form Ralf Browns interrupt list) */
  710. static int
  711. isEGA(void)
  712. {
  713.     union REGS regs;
  714.     regs.h.ah = 0x12;
  715.     regs.h.bl = 0x10;
  716.     regs.h.bh = 0xff;
  717.     int86(0x10, ®s, ®s);
  718.     return(regs.h.bh != 0xff);
  719. }
  720.  
  721.  
  722. extern int _gppconio_init;
  723.  
  724. void gppconio_init(void)
  725. {
  726.     static int oldattrib =  -1;
  727.     if (oldattrib == -1)
  728.         oldattrib = get_screenattrib();   
  729.     _gettextinfo(&txinfo);
  730.     if (txinfo.currmode == 7)    /* MONO */
  731.         ScreenAddress = 0xb0000UL;
  732.     else
  733.     ScreenAddress = 0xb8000UL;
  734.     ScreenAttrib = txinfo.normattr = txinfo.attribute = oldattrib;
  735.     _gppconio_init = 1;
  736. }
  737.  
  738.